// 坐标轴
export enum Axis {
  x,
  y,
  z,
}
// 旋转 + 顺时针  - 逆时针
export type Direction = "+" | "-";

export type Size = number;

// 立方体方位 / 魔方基本方位（还有其他方位）
export enum FacePositionBase {
  up,
  down,
  left,
  right,
  front,
  behind,
}

// 立方体角色
export type CubeRole = "center" | "corner" | "edge";

// 面 颜色枚举
export enum FaceColor {
  // 默认颜色即底色
  default = "rgba(0, 0, 0, 1)",

  // 初始方位颜色值
  up = "yellow",
  down = "white",
  left = "orange",
  right = "red",
  front = "blue",
  behind = "green",
}

export interface FaceConfigItem {
  position: FacePositionBase;
  color: FaceColor;
}

// 立方体颜色
export type FaceColorConfig = {
  [key in FacePositionBase]: FaceColor;
};

export type RotateRatioConfig = {
  [key in Axis]: number;
};

export type TranslateRatioConfig = {
  [key in Axis]: number;
};
export type CubeCoord = [number, number, number];

interface CubeBaseInfo {
  coord: CubeCoord;
  coordAbs: CubeCoord;
  currentCoord: CubeCoord;
  key?: string;
  role?: CubeRole;
}
export interface CubeProps extends CubeBaseInfo {
  faceColorConfig: FaceColorConfig;
  rotateRatioConfig: RotateRatioConfig;
  translateRatioConfig: TranslateRatioConfig;
  shimRotateRatioConfig: RotateRatioConfig;
  boxTransition: boolean;
}

// 获取立方体基本配置
export const getCubeConfigBase = (): {
  [key in FacePositionBase]: FaceConfigItem;
} => {
  return {
    [FacePositionBase.up]: {} as FaceConfigItem,
    [FacePositionBase.down]: {} as FaceConfigItem,
    [FacePositionBase.left]: {} as FaceConfigItem,
    [FacePositionBase.right]: {} as FaceConfigItem,
    [FacePositionBase.front]: {} as FaceConfigItem,
    [FacePositionBase.behind]: {} as FaceConfigItem,
  };
};

// 获取faceColorConfig初始值
const getFaceColorConfig = (options: FaceColorConfig): FaceColorConfig => {
  return Object.assign(
    {
      [FacePositionBase.up]: FaceColor.default,
      [FacePositionBase.down]: FaceColor.default,
      [FacePositionBase.left]: FaceColor.default,
      [FacePositionBase.right]: FaceColor.default,
      [FacePositionBase.front]: FaceColor.default,
      [FacePositionBase.behind]: FaceColor.default,
    },
    options || {}
  );
};
const getRotateRatioConfig = (
  options: RotateRatioConfig
): RotateRatioConfig => {
  return Object.assign(
    {
      [Axis.x]: 0,
      [Axis.y]: 0,
      [Axis.z]: 0,
    },
    options || {}
  );
};
const getTranslateRatioConfig = (
  options: TranslateRatioConfig
): TranslateRatioConfig => {
  return Object.assign(
    {
      [Axis.x]: 0,
      [Axis.y]: 0,
      [Axis.z]: 0,
    },
    options || {}
  );
};

export const getPxVal = (size: Size): string => {
  return `${size}px`;
};

// 获取坐标【各值】中最大值 【同时也是getCubeCoordList初始坐标左移值】
export const getCoordMaxNum = (order: number): number => {
  return (order - 1) / 2;
};
// 获取立方体坐标列表
const getCubeCoordList = (order: number): CubeCoord[] => {
  // 基础坐标可取值
  const valueBase = new Array(order)
    .fill(undefined)
    .map((...[, index]) => index);
  // 以x,y,z中间坐标为坐标系原点; 即 x, y, z都需要往负方向移动 二分之 order 的距离
  const moveNum = getCoordMaxNum(order);
  // 处理之后 坐标可取值
  const valueRes = valueBase.map((item) => item - moveNum);
  // 魔方所有块的坐标
  const list: CubeCoord[] = valueRes.reduce((arr, x) => {
    // 相同x坐标的数组
    const sameXCoordList: CubeCoord[] = [];

    valueRes.forEach((y) => {
      valueRes.forEach((z) => {
        sameXCoordList.push([x, y, z]);
      });
    });

    arr.push(...sameXCoordList);
    return arr;
  }, [] as CubeCoord[]);
  console.log(521, list);
  return list;
};

// 过滤掉内部即看不到的块的坐标 同时设置块的角色 即中心块 角块 棱块 【两个操作放一个函数主要是因为此处coordListAbs已经循环并且生成绝对值 故此】
const filterCubeCoordListAndSetRole = (
  list: CubeCoord[],
  order: number
): CubeBaseInfo[] => {
  const maxNum = getCoordMaxNum(order);
  const baselist = list.map((coord) => {
    // 取绝对值
    const coordAbs = coord.map((val) => Math.abs(val)) as CubeCoord;
    const maxVal = Math.max(...coordAbs);
    const res = {
      coordAbs,
      coord,
      maxVal,
    };
    return res;
  });
  // 有效的 最终需要展示的列表
  const validList = baselist.filter((item) => item.maxVal === maxNum);

  const resultList = validList.map(({ coord, coordAbs }) => {
    return {
      coord,
      currentCoord: [...coord] as CubeCoord,
      coordAbs,
    };
  });
  return resultList;
};

interface SpecificColorParams {
  config: FaceColorConfig;
  val: number;
  index: number;
  order: number;
}
// 获取具体颜色
const getSpecificColor = ({
  order,
  index,
  val,
  config,
}: SpecificColorParams) => {
  if (order === 1) {
    // 一阶魔方的特殊处理
    config[FacePositionBase.up] = FaceColor.up;
    config[FacePositionBase.down] = FaceColor.down;
    config[FacePositionBase.left] = FaceColor.left;
    config[FacePositionBase.right] = FaceColor.right;
    config[FacePositionBase.front] = FaceColor.front;
    config[FacePositionBase.behind] = FaceColor.behind;
    return config;
  }
  const maxNum = getCoordMaxNum(order);
  switch (index) {
    case Axis.x: {
      if (maxNum === val) {
        config[FacePositionBase.right] = FaceColor.right;
      } else if (maxNum === -val) {
        config[FacePositionBase.left] = FaceColor.left;
      }
      break;
    }
    case Axis.y: {
      // y轴正方向是向下 故值大的是底面 特此标注
      if (maxNum === val) {
        config[FacePositionBase.down] = FaceColor.down;
      } else if (maxNum === -val) {
        config[FacePositionBase.up] = FaceColor.up;
      }
      break;
    }
    case Axis.z: {
      if (maxNum === val) {
        config[FacePositionBase.front] = FaceColor.front;
      } else if (maxNum === -val) {
        config[FacePositionBase.behind] = FaceColor.behind;
      }
      break;
    }
  }
  return config;
};
export const getCubeList = (order: number): CubeProps[] => {
  const baseList = getCubeCoordList(order);
  const filterList = filterCubeCoordListAndSetRole(baseList, order);
  const propsList = filterList.map(({ coord, coordAbs, currentCoord }) => {
    return {
      coord,
      currentCoord,
      coordAbs,
      translateRatioConfig: getTranslateRatioConfig(
        coord.reduce((res, val, index) => {
          res[index as Axis.x | Axis.y | Axis.z] = val;
          return res;
        }, {} as TranslateRatioConfig)
      ),
      faceColorConfig: getFaceColorConfig(
        coord.reduce((res, val, index) => {
          return getSpecificColor({
            config: res,
            order,
            val,
            index,
          });
        }, {} as FaceColorConfig)
      ),
      rotateRatioConfig: getRotateRatioConfig({} as RotateRatioConfig),
      shimRotateRatioConfig: getRotateRatioConfig({} as RotateRatioConfig),
      boxTransition: true,
    } as CubeProps;
  });
  return propsList.map((item) => {
    const { coord, faceColorConfig } = item;
    // 非默认底色的数量
    const colorNum = Object.values(faceColorConfig).filter(
      (color) => color !== FaceColor.default
    ).length;
    let role: CubeRole;
    switch (colorNum) {
      case 1: {
        role = "center";
        break;
      }
      case 2: {
        role = "edge";
        break;
      }
      case 3: {
        role = "corner";
        break;
      }
      case 6: {
        // 一阶魔方特殊处理
        role = "center";
        break;
      }
      default: {
        // 当前情况不可能存在 上面已经过滤掉了 放置ts报错
        role = "notExistent" as CubeRole;
      }
    }
    return {
      ...item,
      role,
      key: `${role}_${coord.join("_")}`,
    };
  });
};

// 用做根据各排坐标值最大点 按照旋转方向推算出当前排各个坐标位置 即推算时哪个轴的坐标先变 哪个后变
const axisChangeOrderInfo: {
  [a in Axis]: {
    [d in Direction]: Axis[];
  };
} = {
  [Axis.x]: {
    "+": [Axis.y, Axis.z],
    "-": [Axis.z, Axis.y],
  },
  [Axis.y]: {
    "+": [Axis.z, Axis.x],
    "-": [Axis.x, Axis.z],
  },
  [Axis.z]: {
    "+": [Axis.x, Axis.y],
    "-": [Axis.y, Axis.x],
  },
};
// 获取坐标推算顺序
export const getAxisChangeOrderInfo = (
  axis: Axis,
  direction: Direction
): Axis[] => {
  return axisChangeOrderInfo[axis][direction];
};

// 绕当前轴旋转 操作哪些面开始块相应坐标大于结束块相应坐标是顺时针旋转
export const positiveFace = {
  [Axis.x]: [FacePositionBase.down, FacePositionBase.behind],
  [Axis.y]: [FacePositionBase.left, FacePositionBase.front],
  [Axis.z]: [FacePositionBase.up, FacePositionBase.right],
};

// 推导坐标
const deductionCoord = ({
  currentCoord,
  axis,
  reduceVal,
  axisChangeOrder,
  list,
  maxNum,
}: {
  currentCoord: CubeCoord;
  axis: Axis;
  reduceVal: number;
  axisChangeOrder: Axis[];
  list: CubeCoord[];
  maxNum: number;
}): void => {
  if (!list.find((item) => item.toString() === currentCoord.toString())) {
    list.push(currentCoord);

    const nextCoord: CubeCoord = [...currentCoord];

    let axis_res: Axis = axis;
    let reduceVal_res: number = reduceVal;

    let axisVal = nextCoord[axis] + reduceVal_res;
    if (Math.abs(axisVal) > maxNum) {
      axis_res = axisChangeOrder.find((item) => item !== axis_res);
      axisVal = nextCoord[axis_res] + reduceVal_res;
      if (Math.abs(axisVal) > maxNum) {
        reduceVal_res = -reduceVal_res;
      }
      axisVal = nextCoord[axis_res] + reduceVal_res;
      if (Math.abs(axisVal) > maxNum) {
        return console.warn(`当前排的当前圈只有一个块 [${currentCoord}]`);
      }
    }
    nextCoord[axis_res] = axisVal;
    deductionCoord({
      currentCoord: nextCoord,
      axis: axis_res,
      reduceVal: reduceVal_res,
      axisChangeOrder,
      list,
      maxNum,
    });
  } else {
    // console.log(387, "处理完成");
    // console.log(388, list);
  }
};
export const getDeductionCoordList = (
  topCoord: CubeCoord,
  axisChangeOrder: Axis[],
  maxNum: number
): CubeCoord[] => {
  // 首先变化的坐标
  const [firstChangeAixs] = axisChangeOrder;
  const list: CubeCoord[] = [];
  // console.log(`topCoord`, [...topCoord]);
  // console.log(
  // 401,
  // axisChangeOrder.map((item) => Axis[item])
  // );

  deductionCoord({
    currentCoord: topCoord,
    axis: firstChangeAixs,
    reduceVal: -1,
    axisChangeOrder,
    list,
    maxNum,
  });
  return list;
};

type Translate3dBase = {
  [key in Axis]: number;
};
type RotateDegBase = {
  [key in Axis]: number;
};

// 获取魔方块 面的transform基本参数
export const cubeFaceTransformBaseParams: {
  [f in FacePositionBase]: {
    translate3dBase: Translate3dBase;
    rotateDegBase: RotateDegBase;
  };
} = {
  [FacePositionBase.up]: {
    translate3dBase: { [Axis.x]: 0, [Axis.y]: -0.5, [Axis.z]: 0 },
    rotateDegBase: { [Axis.x]: 1, [Axis.y]: 0, [Axis.z]: 0 },
  },
  [FacePositionBase.down]: {
    translate3dBase: { [Axis.x]: 0, [Axis.y]: 0.5, [Axis.z]: 0 },
    rotateDegBase: { [Axis.x]: -1, [Axis.y]: 0, [Axis.z]: 0 },
  },
  [FacePositionBase.left]: {
    translate3dBase: { [Axis.x]: -0.5, [Axis.y]: 0, [Axis.z]: 0 },
    rotateDegBase: { [Axis.x]: 0, [Axis.y]: -1, [Axis.z]: 0 },
  },
  [FacePositionBase.right]: {
    translate3dBase: { [Axis.x]: 0.5, [Axis.y]: 0, [Axis.z]: 0 },
    rotateDegBase: { [Axis.x]: 0, [Axis.y]: 1, [Axis.z]: 0 },
  },
  [FacePositionBase.front]: {
    translate3dBase: { [Axis.x]: 0, [Axis.y]: 0, [Axis.z]: 0.5 },
    rotateDegBase: { [Axis.x]: 0, [Axis.y]: 0, [Axis.z]: 0 },
  },
  [FacePositionBase.behind]: {
    translate3dBase: { [Axis.x]: 0, [Axis.y]: 0, [Axis.z]: -0.5 },
    rotateDegBase: { [Axis.x]: 0, [Axis.y]: 0, [Axis.z]: 0 },
  },
};
// 获取魔方块 面的transform样式
export const getCubeFaceTransformStyle = (
  position: FacePositionBase,
  size: Size,
  baseDeg = 90
): string => {
  const { translate3dBase, rotateDegBase } =
    cubeFaceTransformBaseParams[position];
  const translate3d = Object.values(translate3dBase).map((item) =>
    getPxVal(item * size)
  );
  const [rotateX, rotateY, rotateZ] = Object.values(rotateDegBase).map(
    (item) => item * baseDeg
  );
  return `translate3d(${translate3d.join(
    ","
  )}) translate(-50%, -50%) rotateX(${rotateX}deg) rotateY(${rotateY}deg) rotateZ(${rotateZ}deg)`;
};

export type OrderPosition = FacePositionBase[];

// 以各面position为key 各面配置为value组成的对象
export type FaceConfigObjectInPosition = {
  [key in FacePositionBase]: FaceConfigItem;
};

// 获取魔方旋转后 更新块的position顺序
export const getPositionChangeOrder = (
  faceConfigObjectInPosition: FaceConfigObjectInPosition,
  axis: Axis,
  isReduce: boolean
): OrderPosition => {
  let res: FacePositionBase[] = [];
  switch (axis) {
    case Axis.x: {
      if (isReduce) {
        res = [
          FacePositionBase.up,
          FacePositionBase.front,
          FacePositionBase.down,
          FacePositionBase.behind,
        ];
      } else {
        res = [
          FacePositionBase.up,
          FacePositionBase.behind,
          FacePositionBase.down,
          FacePositionBase.front,
        ];
      }
      break;
    }
    case Axis.y: {
      if (isReduce) {
        res = [
          FacePositionBase.front,
          FacePositionBase.left,
          FacePositionBase.behind,
          FacePositionBase.right,
        ];
      } else {
        res = [
          FacePositionBase.front,
          FacePositionBase.right,
          FacePositionBase.behind,
          FacePositionBase.left,
        ];
      }
      break;
    }
    case Axis.z: {
      if (isReduce) {
        res = [
          FacePositionBase.up,
          FacePositionBase.left,
          FacePositionBase.down,
          FacePositionBase.right,
        ];
      } else {
        res = [
          FacePositionBase.up,
          FacePositionBase.right,
          FacePositionBase.down,
          FacePositionBase.left,
        ];
      }
      break;
    }
  }
  return res.map((item) => faceConfigObjectInPosition[item].position);
};

// (通过)魔方块的面操作旋转时 当前面相当于哪个轴 即首先排除的当初轴用来推断最终的旋转轴
export const positionQuiteAxisObject = {
  [FacePositionBase.up]: Axis.y,
  [FacePositionBase.down]: Axis.y,
  [FacePositionBase.left]: Axis.x,
  [FacePositionBase.right]: Axis.x,
  [FacePositionBase.front]: Axis.z,
  [FacePositionBase.behind]: Axis.z,
};
